<template>
  <view v-if="show" class="u-tabbar" @touchmove.stop.prevent="() => { }">
    <view class="u-tabbar__content safe-area-inset-bottom" :style="{
      height: $u.addUnit(height),
      backgroundColor: bgColor
    }" :class="{
  'u-border-top': borderTop
}">
      <view class="u-tabbar__content__item" v-for="(item, index) in list" :key="index" :class="{
        'u-tabbar__content__circle': midButton && item.midButton
      }" @tap.stop="clickHandler(index)" :style="{
  backgroundColor: bgColor
}">
        <view :class="[
          midButton && item.midButton
            ? 'u-tabbar__content__circle__button'
            : 'u-tabbar__content__item__button'
        ]" class="tabIcon">
          <u-icon :size="midButton && item.midButton
              ? midButtonSize
              : item.iconSize
                ? item.iconSize
                : iconSize
            " :name="elIconPath(index)" :img-mode="item.imgMode || 'scaleToFill'" :color="elColor(index)"
            :custom-prefix="item.customIcon ? 'custom-icon' : 'uicon'"></u-icon>
          <u-badge :count="item.count" :is-dot="item.isDot" v-if="item.count"
            :offset="[-2, getOffsetRight(item.count, item.isDot)]"></u-badge>
        </view>
        <view class="u-tabbar__content__item__text" :style="{
          color: elColor(index)
        }">
          <text class="u-line-1">{{ item.text }}</text>
        </view>
      </view>
      <view v-if="midButton" class="u-tabbar__content__circle__border" :class="{
        'u-border': borderTop
      }" :style="{
  backgroundColor: bgColor,
  left: midButtonLeft
}"></view>
    </view>
    <!-- 这里加上一个48rpx的高度,是为了增高有凸起按钮时的防塌陷高度(也即按钮凸出来部分的高度) -->
    <view class="u-fixed-placeholder safe-area-inset-bottom" :style="{
      height: `calc(${$u.addUnit(height)} + ${midButton ? 48 : 0}rpx)`
    }"></view>
  </view>
</template>

<script>
import { useConfigStore } from '@/store'

const configStore = useConfigStore()
const pageslist = [
  // {
  //   pagePath: '/pages/shortVideo/index',
  //   iconPath: '/static/home_normal.svg',
  //   selectedIconPath: '/static/home_selected.svg',
  //   iconSize: 50,
  //   text: '首页',
  //   show: true
  // },
  {
    pagePath: '/pages/index/index',
    iconPath: '/static/shop_normal.svg',
    selectedIconPath: '/static/shop_selected.svg',
    iconSize: 48,
    text: '线下门店',
    show: true
  },
  // {
  //   path: '/packageA/pages/tweetEdit/index',
  //   iconPath: '/static/add.svg',
  //   selectedIconPath: '/static/add.svg',
  //   customIcon: true,
  //   iconSize: 80,
  //   imgMode: 'widthFix',
  //   text: '',
  //   show: true
  // },
  {
    pagePath: '/pages/cart/index',
    iconPath: '/static/tabbar/gwc0.svg',
    selectedIconPath: '/static/tabbar/gwc.svg',
    iconSize: 42,
    text: '购物车',
    show: true
  },
  // {
  //   path: '/packageD/pages/index/index',
  //   iconPath: '/static/news_normal.svg',
  //   selectedIconPath: '/static/news_selected.svg',
  //   iconSize: 48,
  //   text: '一码人脉',
  //   show: true
  // },
  {
    pagePath: '/pages/my/index',
    iconPath: '/static/personal_normal.svg',
    selectedIconPath: '/static/personal_selected.svg',
    iconSize: 42,
    text: '我的',
    show: true  
  }
  // {
  //   pagePath: '/pages/mine/index',
  //   iconPath: '/static/personal_normal.svg',
  //   selectedIconPath: '/static/personal_selected.svg',
  //   iconSize: 42,
  //   text: '我的',
  //   show: true
  // }
]
export default {
  emits: ['update:modelValue', 'input', 'change'],
  props: {
    // 通过v-model绑定current值
    value: {
      type: [String, Number],
      default: 0
    },
    modelValue: {
      type: [String, Number],
      default: 0
    },
    // 显示与否
    show: {
      type: Boolean,
      default: true
    },
    // 整个tabbar的背景颜色
    bgColor: {
      type: String,
      default: '#fff'
    },
    // tabbar的高度，默认50px，单位任意，如果为数值，则为rpx单位
    height: {
      type: [String, Number],
      default: '102'
    },
    // 非凸起图标的大小，单位任意，数值默认rpx
    iconSize: {
      type: [String, Number],
      default: 40
    },
    // 凸起的图标的大小，单位任意，数值默认rpx
    midButtonSize: {
      type: [String, Number],
      default: 90
    },
    // 激活时的演示，包括字体图标，提示文字等的演示
    activeColor: {
      type: String,
      default: '#FF6C18'
    },
    // 未激活时的颜色
    inactiveColor: {
      type: String,
      default: '#999999'
    },
    // 是否显示中部的凸起按钮
    midButton: {
      type: Boolean,
      default: false
    },
    // 配置参数
    list: {
      type: Array,
      default() {
        pageslist[2].show = configStore.videoPageOpen
        return pageslist.filter((item) => item.show)
      }
    },
    // 切换前的回调
    beforeSwitch: {
      type: Function,
      default: null
    },
    // 是否显示顶部的横线
    borderTop: {
      type: Boolean,
      default: false
    },
    // 是否隐藏原生tabbar
    hideTabBar: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      // 由于安卓太菜了，通过css居中凸起按钮的外层元素有误差，故通过js计算将其居中
      midButtonLeft: '50%',
      pageUrl: '' // 当前页面URL
    }
  },
  created() {
    // 是否隐藏原生tabbar
    if (this.hideTabBar) uni.hideTabBar()
    // 获取引入了u-tabbar页面的路由地址，该地址没有路径前面的"/"
    const pages = getCurrentPages()
    // 页面栈中的最后一个即为项为当前页面，route属性为页面路径
    this.pageUrl = pages[pages.length - 1].route
  },
  computed: {
    valueCom() {
      // #ifndef VUE3
      return this.value
      // #endif

      // #ifdef VUE3
      return this.modelValue
      // #endif
    },
    elIconPath() {
      return (index) => {
        // 历遍u-tabbar的每一项item时，判断是否传入了pagePath参数，如果传入了
        // 和data中的pageUrl参数对比，如果相等，即可判断当前的item对应当前的tabbar页面，设置高亮图标
        // 采用这个方法，可以无需使用v-model绑定的value值
        const { pagePath } = this.list[index]
        // 如果定义了pagePath属性，意味着使用系统自带tabbar方案，否则使用一个页面用几个组件模拟tabbar页面的方案
        // 这两个方案对处理tabbar item的激活与否方式不一样
        if (pagePath) {
          if (pagePath == this.pageUrl || pagePath == `/${this.pageUrl}`) {
            return this.list[index].selectedIconPath
          }
          return this.list[index].iconPath
        }
        // 普通方案中，索引等于v-model值时，即为激活项
        return index == this.valueCom
          ? this.list[index].selectedIconPath
          : this.list[index].iconPath
      }
    },
    elColor() {
      return (index) => {
        // 判断方法同理于elIconPath
        const { pagePath } = this.list[index]
        if (pagePath) {
          if (pagePath == this.pageUrl || pagePath == `/${this.pageUrl}`)
            return this.activeColor
          return this.inactiveColor
        }
        return index == this.valueCom ? this.activeColor : this.inactiveColor
      }
    }
  },
  mounted() {
    this.midButton && this.getMidButtonLeft()
  },
  methods: {
    async clickHandler(index) {
      if (this.list[index].path) {
        uni.navigateTo({ url: this.list[index].path })
        return
      }
      if (this.beforeSwitch && typeof this.beforeSwitch === 'function') {
        // 执行回调，同时传入索引当作参数
        // 在微信，支付宝等环境(H5正常)，会导致父组件定义的customBack()函数体中的this变成子组件的this
        // 通过bind()方法，绑定父组件的this，让this.customBack()的this为父组件的上下文
        const beforeSwitch = this.beforeSwitch.bind(this.$u.$parent.call(this))(
          index
        )
        // 判断是否返回了promise
        if (!!beforeSwitch && typeof beforeSwitch.then === 'function') {
          await beforeSwitch
            .then((res) => {
              // promise返回成功，
              this.switchTab(index)
            })
            .catch((err) => { })
        } else if (beforeSwitch === true) {
          // 如果返回true
          this.switchTab(index)
        }
      } else {
        this.switchTab(index)
      }
    },
    // 切换tab
    switchTab(index) {
      // 发出事件和修改v-model绑定的值
      this.$emit('change', index)
      // 如果有配置pagePath属性，使用uni.switchTab进行跳转
      if (this.list[index].pagePath) {
        uni.switchTab({
          url: this.list[index].pagePath
        })
      } else {
        // 如果配置了papgePath属性，将不会双向绑定v-model传入的value值
        // 因为这个模式下，不再需要v-model绑定的value值了，而是通过getCurrentPages()适配
        this.$emit('input', index)
        this.$emit('update:modelValue', index)
      }
    },
    // 计算角标的right值
    getOffsetRight(count, isDot) {
      // 点类型，count大于9(两位数)，分别设置不同的right值，避免位置太挤
      if (isDot) {
        return -20
      }
      if (count > 9) {
        return -40
      }
      return -30
    },
    // 获取凸起按钮外层元素的left值，让其水平居中
    getMidButtonLeft() {
      const { windowWidth } = this.$u.sys()
      // 由于安卓中css计算left: 50%的结果不准确，故用js计算
      this.midButtonLeft = `${windowWidth / 2}px`
    }
  }
}
</script>

<style scoped lang="scss">
// 定义混入指令，用于在非nvue环境下的flex定义，因为nvue没有display属性，会报错
@mixin vue-flex($direction: row) {
  /* #ifndef APP-NVUE */
  display: flex;
  flex-direction: $direction;
  /* #endif */
}

.u-fixed-placeholder {
  /* #ifndef APP-NVUE */
  box-sizing: content-box;
  /* #endif */
}

.u-tabbar {

  &__content {
    @include vue-flex;
    align-items: center;
    position: relative;
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    z-index: 998;
    &:nth-child(3) {
      .u-icon__img {
          width: 90rpx;
          height: auto !important;
      }
    }

    /* #ifndef APP-NVUE */
    box-sizing: content-box;
    /* #endif */

    &__circle__border {
      border-radius: 100%;
      width: 110rpx;
      height: 110rpx;
      top: -48rpx;
      position: absolute;
      z-index: 4;
      background-color: #ffffff;
      // 由于安卓的无能，导致只有3个tabbar item时，此css计算方式有误差
      // 故使用js计算的形式来定位，此处不注释，是因为js计算有延后，避免出现位置闪动
      left: 50%;
      transform: translateX(-50%);

      &:after {
        border-radius: 100px;
      }
    }

    &__item {
      flex: 1;
      justify-content: center;
      height: 100%;
      padding: 12rpx 0;
      @include vue-flex;
      flex-direction: column;
      align-items: center;
      position: relative;

      &__button {
        position: absolute;
        top: 14rpx;
        left: 50%;
        transform: translateX(-50%);
      }

      &__text {
        color: $u-content-color;
        font-size: 26rpx;
        line-height: 28rpx;
        position: absolute;
        bottom: 14rpx;
        left: 50%;
        transform: translateX(-50%);
        width: 100%;
        text-align: center;
      }
    }

    &__circle {
      position: relative;
      @include vue-flex;
      flex-direction: column;
      justify-content: space-between;
      z-index: 10;
      /* #ifndef APP-NVUE */
      height: calc(100% - 1px);
      /* #endif */

      &__button {
        width: 90rpx;
        height: 90rpx;
        border-radius: 100%;
        @include vue-flex;
        justify-content: center;
        align-items: center;
        position: absolute;
        background-color: #ffffff;
        top: -40rpx;
        left: 50%;
        z-index: 6;
        transform: translateX(-50%);
      }
    }
  }
}

/* #ifdef H5 */
.tabIcon {
  top: 10rpx !important;
}

.u-tabbar__content__item__text {
  bottom: 10rpx;
}

/* #endif */
</style>
